/*
	skinnedsubmesh.h

	Copyright (C) 2004 WildTangent, Inc. 
	All Rights Reserved

	Travis Baldree
	9/4/2004

*/

#ifndef _SKINNEDSUBMESH_H
#define _SKINNEDSUBMESH_H

#include <assert.h>


class	CSkinnedMeshSegment;
class	CRefManager;
class	CMaterial;
class	CActiveSkinnedAnimation;
class	CShadowVolume;
class	CSettings;
class	CWeightedVertex;
class	CSkeleton;
class	CPose;

/// sub-meshes of the parent skinned mesh, are
/// basically a collection of submesh segments.
/// the submesh contains the vertex buffer and index buffer, and the
/// segments reference the vert and index buffer 
class CSkinnedSubMesh
{
public:

				CSkinnedSubMesh();
				~CSkinnedSubMesh();

	void		CreateVB( LPDIRECT3DDEVICE9 pD3DDevice,								// direct3d device
								uint32 Faces,										// faces in the model
								std::vector <CWeightedVertex*>& WeightedVertices,	// vector of vertices
								std::vector <D3DXVECTOR3>& UVs );					// vector of uvs



	uint32		AddAnimatedMeshSegment( CRefManager& pRefManager,				// reference to refmanager
										CSettings& pSettings,						// pointer to the settings manager, for keeping track of card/machine capabilities
										LPDIRECT3DDEVICE9 pD3DDevice,			// direct3d device
										std::vector <D3DXVECTOR4>& Triangles,	// vector of triangle indices
										uint32 MaterialID,						// material id
										int32 MaterialType, 					// material type
										bool DoubleSided );						// double sided material

	void		SetMaterial( CMaterial* pMaterial,				// material to apply
							 uint32 SubSegment );				// subsegment to apply to

	void	EnableShadows( LPDIRECT3DDEVICE9 pD3DDevice );		// direct3d device

	void	RenderShadows( LPDIRECT3DDEVICE9 pD3DDevice,			// direct3d device
						   const D3DXMATRIX& CameraSpaceMatrix,		// camera space matrix
						   const D3DXVECTOR3& Light );				// direction of light shadow is being cast from

	void	RenderShadows( LPDIRECT3DDEVICE9 pD3DDevice,			// direct3d device
						   const D3DXMATRIX& CameraSpaceMatrix );	// camera space matrix

	void SetMaxBounds( const D3DXVECTOR3& Bounds )	{	m_MaxBounds = Bounds;	};
	void SetMinBounds( const D3DXVECTOR3& Bounds )	{	m_MinBounds = Bounds;	};

	const D3DXVECTOR3& MaxBounds( void )		{	return m_MaxBounds;		};

	const D3DXVECTOR3& MinBounds( void )		{	return m_MinBounds;		};

	uint32 TotalVertices( void )				{	return m_TotalVertices;	};
	uint32 TotalFaces( void )					{	return m_TotalFaces;	};

	uint32							SkinnedMeshSegments( void )	{	return m_pSkinnedMeshSegments.size();		};

	CSkinnedMeshSegment&			GetSkinnedMeshSegment( uint32 Index )
	{
		assert( Index <= m_pSkinnedMeshSegments.size() );
		return *m_pSkinnedMeshSegments[Index];
	};

	LPDIRECT3DVERTEXBUFFER9 GetVB( void )			{	return m_pVB;				};
	LPDIRECT3DINDEXBUFFER9	GetIB( void )			{	return m_pIB;				};

	void			InvalidateDeviceObjects( void );
	void			RestoreDeviceObjects( LPDIRECT3DDEVICE9 pD3DDevice );	// direct3d device

	void							UpdateVB( CPose* pBlendedPose );											// final blended pose

	void							RenderNoTexture( LPDIRECT3DDEVICE9 pD3DDevice );	// direct3d device

	std::string						Name( void )							{ return m_Name; };
	void							SetName( const std::string& Name )		{ m_Name = Name; };

	void							CleanIB( LPDIRECT3DDEVICE9 pD3DDevice );	// d3d device

	void							SetVisible( uint32 SubSegment,			// subsegment to apply to
												bool State );				// state to set

	void							SetSkeleton( CSkeleton* pSkeleton )		{	m_pSkeleton = pSkeleton;	};

private:
	uint32							m_TotalFaces;		// total faces in this mesh
	uint32							m_TotalVertices;	// total vertices in this mesh
	uint32							m_CurrentIndex;

	std::string						m_Name;

	LPDIRECT3DVERTEXBUFFER9			m_pVB;
	LPDIRECT3DINDEXBUFFER9			m_pIB;			// index buffer for this sub-mesh

	CShadowVolume*					m_pShadowVolume;

	CSkeleton*						m_pSkeleton;

	CPose*							m_pCurrentPose;

	D3DXVECTOR3						m_MaxBounds;
	D3DXVECTOR3						m_MinBounds;

	bool							m_ShadowsEnabled;	// casts shadows?

	std::vector <CWeightedVertex*>	m_pWeightedVertices;

	std::vector <CSkinnedMeshSegment*>	m_pSkinnedMeshSegments;


};

#endif 